/**
 * @file tech_hsc.h
 * @author your name (you@domain.com)
 * @brief 工艺指令相关,高速脉冲计数器，和硬件强相关，参考张宾：encode.c/h中的相关实现代码
 * @version 0.1
 * @date 2025-08-07
 *
 * @copyright Copyright (c) 2025
 *
 */
#include "stm32f4xx_hal.h"
#include "stm32f407xx.h"
#include "stm32f4xx_hal_tim.h"
#include "sysconf.h"
#include "xmzTypeDefine.h"
#include <stdint.h>
#ifndef TECH_HSC_H
#define TECH_HSC_H
enum HSC_CH {
  HSC_1 = 0, //<! 高速计数器1
  HSC_2,     //<! 高速计数器2
  HSC_3,     //<! 高速计数器3
  HSC_4,     //<! 高速计数器4
  HSC_5,     //<! 高速计数器5
  HSC_6,     //<! 高速计数器6
};
/**
 * @brief 高速计数器状态枚举
 *
 * 定义了高速计数器操作的各种状态码，用于指示操作结果和错误类型。
 * 状态码分为无错误状态(0x0000)和错误状态(0x80xx)两类。
 */
enum HSC_STATUS {
  HSC_STATUS_NOERROR        = 0x0000, //<! 无错误
  HSC_STATUS_ERR_CH_NUM     = 0x80A1, //<! 高速计数器的硬件标识符无效
  HSC_STATUS_ERR_NEW_DIR    = 0x80B1, //<! 计数方向(NEW_DIR)无效
  HSC_STATUS_ERR_NEW_CV     = 0x80B2, //<! 计数值(NEW_CV)无效
  HSC_STATUS_ERR_NEW_RV     = 0x80B3, //<! 参考值(NEW_RV)无效
  HSC_STATUS_ERR_NEW_PERIOD = 0x80B4, //<! 频率测量周期(NEW_PERIOD)无效
  HSC_STATUS_ERR_REPEATED   = 0x80C0, //<! 多次访问高速计数器
  HSC_STATUS_ERR_NOT_ON     = 0x80D0, //<! CPU 硬件配置中没有启用高速计数器(HSC)
};
typedef uint8_t HW_HSC;
/**
 * @brief 控制高速计数器结构体
 *
 * 该结构体用于控制和配置高速计数器的各项参数，包括计数方向、初始值、
 * 参考值等，实现对高速计数器的精确控制。
 */
typedef struct {
  UInt hsc;       //!< 高速计数器的硬件地址 (HW-ID)，标识具体哪个计数器
  Bool dir;       //!< 方向控制位，置位时更新计数方向
  Bool cv;        //!< 计数值控制位，置位时更新初始计数值
  Bool rv;        //!< 参考值控制位，置位时更新参考值
  Bool period;    //!< 周期控制位，置位时更新频率测量周期
  Int  new_dir;   //!< 计数方向定义高速计数器是加计数还是减计数。计数方向通过输入 NEW_DIR 的以下值来定义：1 = 加计数，-1
                  //!< =减计数。 只有通过程序参数设置方向控制后，才能使用“控制高速计数器”指令更改计数方向。输入
                  //!< NEW_DIR指定的计数方向将在置位输入 DIR 位时装载到高速计数器。
  DInt new_cv;    //!< 计数值是高速计数器开始计数时使用的初始值。计数值的范围为 -2147483648 到 2147483647。输入 NEW_CV
                  //!< 指定的计数值将在置位输入 CV 位时装载到高速计数器
  DInt new_rv;    //!< 可以通过比较参考值和当前计数器的值，以便触发一个报警。与计数值类似，参考值的范围为 -2147483648 到
                  //!< 2147483647。输入 NEW_RV 指定的参考值将在置位输入 RV 位时装载到高速计数器。
  Int new_period; //!< 频率测量周期通过输入 NEW_PERIOD 的以下值来指定：10 = 0.01s，100 = 0.1s，1000 =
                  //!< 1s。如果为指定高速计数器组态了“测量频率”功能，那么可以更新该时间段。输入 NEW_PERIOD
                  //!< 中指定的时间段将在置位输入 PERIOD 位时装载到高速计数器
  Bool busy;      //!< 忙标志，指示高速计数器是否正在处理中
  Word status;    //!< 状态字，反映操作结果和错误信息
} CTRL_HSC_S;
void CTRL_HSC_S_pack(CTRL_HSC_S* s_ptr, uint8_t* buffer, size_t buffer_size, uint16_t byte_offset);
void CTRL_HSC_S_unpack(CTRL_HSC_S* s_ptr, uint8_t* buffer, size_t buffer_size, uint16_t byte_offset);

// TODO 测量周期和比较值还未作处理
// TODO 暂不支持西门子的反向计数，没有信号线只能加
/**
 * @brief 高速计数器配置结构体
 *
 * 该结构体用于配置和管理STM32定时器实现的高速计数器功能，
 * 支持加计数和减计数模式，可设置初始值，适用于编码器信号处理等场景。
 */
typedef struct {
  TIM_TypeDef*      TIMx;           //!< 定时器实例（如TIM2, TIM3等）
  uint32_t          Channel;        //!< 输入捕获通道（如TIM_CHANNEL_1, TIM_CHANNEL_2）
  GPIO_TypeDef*     GPIO_Port;      //!< GPIO端口（如GPIOA, GPIOB等）
  uint16_t          GPIO_Pin;       //!< GPIO引脚（如GPIO_PIN_1, GPIO_PIN_3等）
  uint8_t           GPIO_AF;        //!< GPIO复用功能选择（如GPIO_AF1_TIM2等）
  TIM_HandleTypeDef htim;           //!< HAL库定时器句柄
  uint32_t          overflow_count; //!< 溢出计数，记录定时器溢出次数，支持负数
  uint8_t           direction;      //!< 计数方向：0-加计数，1-减计数
  uint32_t          initial_value;  //!< 初始值，计数器启动时的设定值，范围-2147483648到2147483647
  uint8_t           active;         //!< 激活状态：0-未启用，1-已启用
} HSCConf;
Bool CTRL_HSC_C(Bool en, CTRL_HSC_S* instance);
Bool StartHSCCapture(enum HSC_CH ch, int8_t direction, int32_t inittial_value);
void All_HSC_Init(void);
void updataHSC(void);
#endif
